UPCE.js ➔ ???   B
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 5
c 6
b 0
f 0
nc 8
nop 2
dl 0
loc 42
rs 8.439
1
// Encoding documentation:
2
// https://en.wikipedia.org/wiki/Universal_Product_Code#Encoding
3
//
4
// UPC-E documentation:
5
// https://en.wikipedia.org/wiki/Universal_Product_Code#UPC-E
6
7
import encode from './encoder';
8
import Barcode from "../Barcode.js";
9
import { checksum } from './UPC.js';
10
11
const EXPANSIONS = [
12
	"XX00000XXX",
13
	"XX10000XXX",
14
	"XX20000XXX",
15
	"XXX00000XX",
16
	"XXXX00000X",
17
	"XXXXX00005",
18
	"XXXXX00006",
19
	"XXXXX00007",
20
	"XXXXX00008",
21
	"XXXXX00009"
22
];
23
24
const PARITIES = [
25
	["EEEOOO", "OOOEEE"],
26
	["EEOEOO", "OOEOEE"],
27
	["EEOOEO", "OOEEOE"],
28
	["EEOOOE", "OOEEEO"],
29
	["EOEEOO", "OEOOEE"],
30
	["EOOEEO", "OEEOOE"],
31
	["EOOOEE", "OEEEOO"],
32
	["EOEOEO", "OEOEOE"],
33
	["EOEOOE", "OEOEEO"],
34
	["EOOEOE", "OEEOEO"]
35
];
36
37
class UPCE extends Barcode{
38
	constructor(data, options){
39
		// Code may be 6 or 8 digits;
40
		// A 7 digit code is ambiguous as to whether the extra digit
41
		// is a UPC-A check or number system digit.
42
		super(data, options);
43
		this.isValid = false;
44
		if(data.search(/^[0-9]{6}$/) !== -1){
45
			this.middleDigits = data;
46
			this.upcA = expandToUPCA(data, "0");
47
			this.text = options.text ||
48
				`${this.upcA[0]}${data}${this.upcA[this.upcA.length - 1]}`;
49
			this.isValid = true;
50
		}
51
		else if(data.search(/^[01][0-9]{7}$/) !== -1){
52
			this.middleDigits = data.substring(1, data.length - 1);
53
			this.upcA = expandToUPCA(this.middleDigits, data[0]);
54
55
			if(this.upcA[this.upcA.length - 1] === data[data.length - 1]){
56
				this.isValid = true;
57
			}
58
			else{
59
				// checksum mismatch
60
				return;
61
			}
62
		}
63
		else{
64
			return;
65
		}
66
67
		this.displayValue = options.displayValue;
68
69
		// Make sure the font is not bigger than the space between the guard bars
70
		if(options.fontSize > options.width * 10){
71
			this.fontSize = options.width * 10;
72
		}
73
		else{
74
			this.fontSize = options.fontSize;
75
		}
76
77
		// Make the guard bars go down half the way of the text
78
		this.guardHeight = options.height + this.fontSize / 2 + options.textMargin;
79
	}
80
81
	valid(){
82
		return this.isValid;
83
	}
84
85
	encode(){
86
		if(this.options.flat){
87
			return this.flatEncoding();
88
		}
89
		else{
90
			return this.guardedEncoding();
91
		}
92
	}
93
94
	flatEncoding(){
95
		var result = "";
96
97
		result += "101";
98
		result += this.encodeMiddleDigits();
99
		result += "010101";
100
101
		return {
102
			data: result,
103
			text: this.text
104
		};
105
	}
106
107
	guardedEncoding(){
108
		var result = [];
109
110
		// Add the UPC-A number system digit beneath the quiet zone
111
		if(this.displayValue){
112
			result.push({
113
				data: "00000000",
114
				text: this.text[0],
115
				options: {textAlign: "left", fontSize: this.fontSize}
116
			});
117
		}
118
119
		// Add the guard bars
120
		result.push({
121
			data: "101",
122
			options: {height: this.guardHeight}
123
		});
124
125
		// Add the 6 UPC-E digits
126
		result.push({
127
			data: this.encodeMiddleDigits(),
128
			text: this.text.substring(1, 7),
129
			options: {fontSize: this.fontSize}
130
		});
131
132
		// Add the end bits
133
		result.push({
134
			data: "010101",
135
			options: {height: this.guardHeight}
136
		});
137
138
		// Add the UPC-A check digit beneath the quiet zone
139
		if(this.displayValue){
140
			result.push({
141
				data: "00000000",
142
				text: this.text[7],
143
				options: {textAlign: "right", fontSize: this.fontSize}
144
			});
145
		}
146
147
		return result;
148
	}
149
150
	encodeMiddleDigits() {
151
		const numberSystem = this.upcA[0];
152
		const checkDigit = this.upcA[this.upcA.length - 1];
153
		const parity = PARITIES[parseInt(checkDigit)][parseInt(numberSystem)];
154
		return encode(this.middleDigits, parity);
155
	}
156
}
157
158
function expandToUPCA(middleDigits, numberSystem) {
159
	const lastUpcE = parseInt(middleDigits[middleDigits.length - 1]);
160
	const expansion = EXPANSIONS[lastUpcE];
161
162
	let result = "";
163
	let digitIndex = 0;
164
	for(let i = 0; i < expansion.length; i++) {
165
		let c = expansion[i];
166
		if (c === 'X') {
167
			result += middleDigits[digitIndex++];
168
		} else {
169
			result += c;
170
		}
171
	}
172
173
	result = `${numberSystem}${result}`;
174
	return `${result}${checksum(result)}`;
175
}
176
177
export default UPCE;
178